/**
 * 
 */
package cn.agiledata.bank.common.util;

import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SecurityUtil {
	
	private static Log log = LogFactory.getLog(SecurityUtil.class);
	private static final String key="CF2D0B9CCBC803FF89CB3FCAF54B61E9";



	// md5()信息摘要, 不可逆
	public static byte[] md5(byte[] input) throws Exception {
		java.security.MessageDigest alg = java.security.MessageDigest
				.getInstance("MD5"); // or "SHA-1"
		log.debug("摘要前的二进串:" + byte2hex(input));
		log.debug("摘要前的字符串:" + new String(input));
		
		alg.update(input);
		byte[] digest = alg.digest();
		log.debug("摘要后的二进串:" + byte2hex(digest));
		return digest;
	}
	
	public static String encryptoMD5String (String origin) {
		
		if (origin == null) {
			return null ;
		}
		
		if (origin.length() == 0) {
			return origin ;
		}
		
		try {
			//byte[] after = md5 (origin.getBytes()) ;
			//return new String (after) ;
			MD5 md5 = new MD5();
			return md5.getMD5ofStr(origin);
		} catch (Exception e) {
			log.error(e) ;
			return origin ;
		}
		
	}

	// 字节码转换成16进制字符串
	public static String byte2hex(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else
				hs = hs + stmp;
			if (n < b.length - 1)
				hs = hs + ":";
		}
		return hs.toUpperCase();
	}
	
	 /**
     * 填充80数据，首先在数据块的右边追加一个'80',如果结果数据块是8的倍数，不再进行追加,如果不是,追加0x00到数据块的右边，直到数据块的长度是8的倍数。
     *
     * @param data 待填充80的数据
     * @return
     */
    public static String padding80(String data) {
        int padlen = 8 - (data.length() / 2) % 8;
        String padstr = "";
        for (int i = 0; i < padlen - 1; i++)
            padstr += "00";
        data = data + "80" + padstr;
        return data;
    }
	
	
	 /**
     * ECB模式中的DES/3DES/TDES算法(数据不需要填充),支持8、16、24字节的密钥 说明：3DES/TDES解密算法 等同与
     * 先用前8个字节密钥DES解密 再用中间8个字节密钥DES加密 最后用后8个字节密钥DES解密 一般前8个字节密钥和后8个字节密钥相同
     *
     * @param key  加解密密钥(8字节:DES算法 16字节:3DES/TDES算法
     *             24个字节:3DES/TDES算法,一般前8个字节密钥和后8个字节密钥相同)
     * @param data 待加/解密数据(长度必须是8的倍数)
     * @param mode 0-加密，1-解密
     * @return 加解密后的数据 为null表示操作失败
     */
    public static String desecb(String key, String data, int mode) {
        try {

            // 判断加密还是解密
            int opmode = (mode == 0) ? Cipher.ENCRYPT_MODE
                    : Cipher.DECRYPT_MODE;

            SecretKey keySpec = null;

            Cipher enc = null;

            // 判断密钥长度
            if (key.length() == 16) {
                // 生成安全密钥
                keySpec = new SecretKeySpec(str2bytes(key), "DES");// key

                // 生成算法
                enc = Cipher.getInstance("DES/ECB/NoPadding");
            } else if (key.length() == 32) {
                // 计算加解密密钥，即将16个字节的密钥转换成24个字节的密钥，24个字节的密钥的前8个密钥和后8个密钥相同,并生成安全密钥
                keySpec = new SecretKeySpec(str2bytes(key
                        + key.substring(0, 16)), "DESede");// 将key前8个字节复制到keyecb的最后8个字节

                // 生成算法
                enc = Cipher.getInstance("DESede/ECB/NoPadding");
            } else if (key.length() == 48) {
                // 生成安全密钥
                keySpec = new SecretKeySpec(str2bytes(key), "DESede");// key

                // 生成算法
                enc = Cipher.getInstance("DESede/ECB/NoPadding");
            } else {
            	log.info("Key length is error");
                return null;
            }

            // 初始化
            enc.init(opmode, keySpec);

            // 返回加解密结果
            return (bytesToHexString(enc.doFinal(str2bytes(data))))
                    .toUpperCase();// 开始计算
        } catch (Exception e) {
        	log.info(e.getMessage());
        }
        return null;
    }
    /**
    * 将16进制组成的字符串转换成byte数组 例如 hex2Byte("0710BE8716FB"); 将返回一个byte数组
    * b[0]=0x07;b[1]=0x10;...b[5]=0xFB;
    *
    * @param src 待转换的16进制字符串
    * @return
    */
   public static byte[] str2bytes(String src) {
       if (src == null || src.length() == 0 || src.length() % 2 != 0) {
           return null;
       }
       int nSrcLen = src.length();
       byte byteArrayResult[] = new byte[nSrcLen / 2];
       StringBuffer strBufTemp = new StringBuffer(src);
       String strTemp;
       int i = 0;
       while (i < strBufTemp.length() - 1) {
           strTemp = src.substring(i, i + 2);
           byteArrayResult[i / 2] = (byte) Integer.parseInt(strTemp, 16);
           i += 2;
       }
       return byteArrayResult;
   }
   
   /**
    * 将byte数组转换成16进制组成的字符串 例如 一个byte数组 b[0]=0x07;b[1]=0x10;...b[5]=0xFB;
    * byte2hex(b); 将返回一个字符串"0710BE8716FB"
    *
    * @param bytes 待转换的byte数组
    * @return
    */
   public static String bytesToHexString(byte[] bytes) 
   {
       if (bytes == null) {
           return "";
       }
       StringBuffer buff = new StringBuffer();
       int len = bytes.length;
       for (int j = 0; j < len; j++) {
           if ((bytes[j] & 0xff) < 16) {
               buff.append('0');
           }
           buff.append(Integer.toHexString(bytes[j] & 0xff));
       }
       return buff.toString();
   }
	public static void main(String[] args) throws Exception {
		
		// byte[] key = getKey();
		//byte[] key = "好好学习".getBytes();
		//decode(encode("测试加密".getBytes(), key), key);
		String ss = "123455" ;
		String after_1 = encryptoMD5String (ss) ;
		String after_2 = encryptoMD5String (ss) ;
		String after_3 = encryptoMD5String ("123456") ;
		
		log.debug(after_1);
		log.info(after_1);
	}
	
	/*
     * 将16进制数字解码成字符串,适用于所有字符（包括中文）
     */
    public static String hexStringToString(String bytes) throws UnsupportedEncodingException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(
                bytes.length() / 2);
        final String hexString = "0123456789abcdef";
        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString
                    .indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray(), "UTF-8");
    }
    
    /*
     * 将字符串编码成16进制数字,适用于所有字符（包括中文）
     */
    public static String encodeHexString(String str) {
        // 根据默认编码获取字节数组
        byte[] bytes = str.getBytes();
        final String hexString = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        // 将字节数组中每个字节拆解成2位16进制整数
        for (int i = 0; i < bytes.length; i++) {
            sb.append(hexString.charAt((bytes[i] & 0xf0) >> 4));
            sb.append(hexString.charAt((bytes[i] & 0x0f) >> 0));
        }
        return sb.toString();
    }
}